package com.quectel.business.pay.handler;


import com.quectel.business.pay.handler.model.BusinessIntegrityCheckStrategy;
import com.quectel.business.pay.handler.model.CreateBusinessResp;
import com.quectel.business.pay.vo.CreateOrderRequest;
import com.quectel.pay.module.order.dto.PayOrderDto;
import com.quectel.pay.module.order.dto.PayOrderRefundDto;
import com.quectel.util.common.Response;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;

/**
 * 支付业务处理 方法需要保持幂等性
 *
 * @author caolu
 */
public interface BasePayHandler {

    /**
     * 获取Controller所携带的HttpRequest对象
     *
     * @return
     */
    default HttpServletRequest getCurrentHttpRequest() {
        return ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
    }

    /**
     * 获取Controller所携带的HttpResponse对象
     *
     * @return
     */
    default HttpServletResponse getCurrentHttpResponse() {
        return ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();
    }

    /**
     * 创建业务订单 返回业务类型等信息
     *
     * @param req
     * @return
     */
    Response<CreateBusinessResp> createBusinessOrder(CreateOrderRequest req);

    /**
     * 创建通用订单成功 可以用于业务订单绑定通用订单
     *
     * @param notifyOrder
     * @return
     */
    Response<Object> createOrderSuccessNotify(PayOrderDto notifyOrder);

    /**
     * 创建通用订单失败 可以根据需要清理已经创建好的订单（垃圾无用订单）
     *
     * @param req
     * @return
     */
    Response<Object> createOrderFailedNotify(CreateOrderRequest req);

    /**
     * 取消订单
     *
     * @param cancelOrder
     * @return
     */
    Response<Object> cancelOrder(PayOrderDto cancelOrder);

    /**
     * 支付成功
     *
     * @param order
     * @return
     */
    Response<Object> paySuccessNotify(PayOrderDto order);


    /**
     * 该方法需要消息队列支持，目前没有实现
     * <pre>
     * 支付成功后默认的业务完整性检查策略
     * 用于以下场景：
     *      支付完成不代表真正的完成。
     *      以共享单车为例，A和B两个用户一起扫码支付开锁，两个人都支付成功，如果A开成功了B没有开锁成功，那么我们需要对A和B不同的业务处理。
     *      这个时候我们开启业务完整性检查。可以设置开启检查，延迟2秒检查，最多通知10次，那么系统会在两秒后调用businessIntegrityCheckNotify方法
     *      以通知业务检查该订单的整体业务情况，如果businessIntegrityCheckNotify方法返回成功则在第四秒继续调用，如果失败则继续调用每次加2秒，直到成功或者达到最大次数
     * </pre>
     *
     * @return 默认值为不检查
     */
    default BusinessIntegrityCheckStrategy businessIntegrityCheckStrategy() {
        return BusinessIntegrityCheckStrategy.DEFAULT;
    }

    /**
     * 完整性检查的延迟回调通知，在此位置实现业务的检查（发起退款，重置业务订单状态等）
     *
     * @param successOrderDetail
     * @return
     */
    default boolean businessIntegrityCheckNotify(PayOrderDto successOrderDetail) {
        return true;
    }


    /**
     * 退款前的前置校验
     *
     * @param payOrderDto
     * @param refundAmount
     * @return
     */
    Response<Object> refundPreCheck(PayOrderDto payOrderDto, BigDecimal refundAmount);

    /**
     * 退款成功
     *
     * @param refundOrder
     * @return
     */
    Response<Object> refundSuccessNotify(PayOrderRefundDto refundOrder);


}
